package com.lion.seaman.worker.plugin;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidPooledConnection;
import com.lion.seaman.common.tools.MD5Tools;
import org.springframework.core.io.support.PropertiesLoaderUtils;

import java.io.IOException;
import java.sql.*;
import java.util.*;

public class JdbcPlugin implements Plugin {
    Properties properties = null;
    DruidDataSource dataSource;
    String url;
    String password;
    String userName;
    String driverClassName;

    public JdbcPlugin() {
    }

    @Override
    public String toString() {
        final StringBuffer sb = new StringBuffer("JdbcPlugin{");
        sb.append("properties=").append(properties);
        sb.append(", url='").append(url).append('\'');
        sb.append(", password='").append(password).append('\'');
        sb.append(", userName='").append(userName).append('\'');
        sb.append(", driverClassName='").append(driverClassName).append('\'');
        sb.append('}');
        return sb.toString();
    }

    public String createPluginId() {
        return MD5Tools.generateMD5(this.toString());
    }

    public JdbcPlugin(String url, String userName, String password, String driverClassName) {
        this.url = url;
        this.userName = userName;
        this.password = password;
        this.driverClassName = driverClassName;
    }

    public JdbcPlugin load(String propertiesFilePath) throws IOException {
        this.properties = PropertiesLoaderUtils.loadAllProperties(propertiesFilePath);
        return this;
    }

    private Object getProperties(Properties properties, String key) {
        Object o = properties.get(key);
        if (o == null) {
            return "";
        }
        return o;
    }

    private DruidDataSource createDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.configFromPropety(properties);
        dataSource.setDriverClassName(properties.getProperty("druid.driverClassName"));
        dataSource.setUrl(properties.getProperty("druid.url"));
        dataSource.setUsername(properties.getProperty("druid.username"));
        dataSource.setPassword(properties.getProperty("druid.password"));
        if (properties.getProperty("druid.maxActive") != null) {
            dataSource.setMaxActive(Integer.valueOf(properties.getProperty("druid.maxActive")));
        }
        return dataSource;
    }

    private DruidDataSource createDataSource(String url, String userName, String password, String driverClassName) {
        this.url = url;
        this.userName = userName;
        this.password = password;
        this.driverClassName = driverClassName;
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setPassword(password);
        dataSource.setUsername(userName);
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driverClassName);
        return dataSource;
    }


    public void ckDataSource() {
        JdbcPlugin plugin = (JdbcPlugin) PluginCache.CACHE.getPlugin(createPluginId());
        if (plugin != null) {
            this.dataSource = plugin.dataSource;
        }
        if (dataSource == null || !dataSource.isEnable()) {
            if (this.properties != null) {
                dataSource = createDataSource();
            } else {
                dataSource = createDataSource(this.url, this.userName, this.password, this.driverClassName);
            }
            PluginCache.CACHE.addPlugin(this);
        }
    }

    public Connection getConn() throws SQLException {
        ckDataSource();
        DruidPooledConnection connection = this.dataSource.getConnection();
        return connection;
    }


    public int executeUpdate(String sql) throws SQLException {
        Connection conn = null;
        Statement statement = null;
        int result = 0;
        try {
            conn = getConn();
            conn.setAutoCommit(false);
            statement = conn.createStatement();
            result = statement.executeUpdate(sql);
            conn.commit();
            conn.setAutoCommit(true);
        } finally {
            statement.close();
            conn.close();
        }
        return result;
    }

    public List<Map<String, Object>> execute(String sql) throws SQLException {
        List<Map<String, Object>> result = new ArrayList<>();
        Connection conn = getConn();
        Statement statement = null;
        try {
            statement = conn.createStatement();
            boolean execute = statement.execute(sql);
            if (execute) {
                ResultSet resultSet = statement.getResultSet();
                ResultSetMetaData metaData = resultSet.getMetaData();
                int columnCount = metaData.getColumnCount();
                while (resultSet.next()) {
                    Map<String, Object> row = new LinkedHashMap<>();
                    for (int i = 1; i <= columnCount; i++) {
                        String columnName = metaData.getColumnName(i);
                        Object object = resultSet.getObject(i);
                        row.put(columnName, object);
                    }
                    result.add(row);
                }
            }
        } finally {
            if (statement != null) {
                statement.close();
            }
            if (conn != null) {
                conn.close();
            }
        }
        return result;
    }


    public static void main(String[] args) throws IOException, SQLException {
        //JdbcPlugin plugin = new JdbcPlugin().load("application.properties");
        // System.out.println(plugin.execute("select * from api_sys_user"));
        //System.out.println(plugin.executeUpdate("insert into api_sys_user values(0,'liyongyao2','sasdf',1,23)"));
        JdbcPlugin plugin1 = new JdbcPlugin("jdbc:presto://hadoop:8889/hive/report", "hive", "**empty**", "com.facebook.presto.jdbc.PrestoDriver");
        System.out.println(plugin1.execute("select * from ad_app limit 2"));


    }

    @Override
    public void close() {
        if (this.dataSource != null) {
            this.dataSource.close();
        }
    }
}
